#!/usr/bin/python
'''
rewrite of creator.c in Python
this also works with PyPy1.8

run:
	~/pypy-1.8/bin/pypy creator.py

'''
import os, sys, ctypes
sys.path.append( '../' )
import libblender as blender
assert blender
ISPYTHON3 = sys.version_info[0] == 3

class _bpy(object):
	def _get_data(self):
		main = self.BContext.CTX_data_main()
		return main
	data = property( _get_data )

	def __init__(self):
		syshandle = 0
		self.BContext = C = blender.CTX_create()
		print( 'Evil C', C )
		ba = blender.bArgs()
		#setCallbacks()
		blender.BLI_init_program_path( os.path.abspath('.') )

		blender.BLI_threadapi_init()
		print('threadapi init done')
		# RNA_init is probably not required, setup of mathutils and python to Data API hooks,
		# defined in source/blender/python/intern/bpy_rna.c
		#blender.RNA_init()

		blender.RE_engines_init()
		print('RE engines init done')

		#blender.pluginapi_force_ref()	# deprecated?

		blender.init_nodesystem()
		print('init node system ok')
		blender.initglobals()			#/* blender.c */
		print('init globals ok')
		blender.IMB_init()
		print('IMB init ok')
		blender.BLI_cb_init()
		print('BLI cb ok')

		#if with game engine: syshandle = blender.SYS_GetSystem()


		_argv = ''
		for arg in sys.argv: _argv += arg + ' '
		if ISPYTHON3: _argv = bytes( _argv, 'utf-8' )
		#argc = len(sys.argv)
		#argv = ctypes.pointer(ctypes.c_char_p(_argv))
		argc = 0		# BLI_argsInit can segfault with bad args!
		argv = ctypes.pointer(ctypes.c_char_p(''))
		ba = blender.BLI_argsInit(argc, argv)
		print('BLI args init ok')


		## calls setupArguments first - just sets up some extra callbacks
		print(ba,dir(ba))
		ba.Parse(1, None, None)  # required, segfaults without this?
		print('BLI args parsed')


		print('BKE font register builtin...')
		bfont = ctypes.cast(
			blender.CTYPES_DLL.datatoc_Bfont, ctypes.POINTER(ctypes.c_void_p)
		)
		bfontsize = ctypes.cast(
			blender.CTYPES_DLL.datatoc_Bfont_size, ctypes.POINTER(ctypes.c_int)
		).contents
		blender.BKE_font_register_builtin(
			bfont, 
			bfontsize
		)

		blender.sound_init_once()
		blender.init_def_material()

		if '--headless' in sys.argv:
			print('headless mode')
			ba.Parse(3, None, None)
			## WM_init is still called in background mode!? see creator.c:1298
			if False:
				print('trying WM_init...')
				C.WM_init( argc, argv )
				print('WM init ok')
			blender.BLI_init_temporary_dir(None)	# ignore user preferences
			print('temp dir set to None')
		else:
			ba.Parse(2, None, None)
			ba.Parse(3, None, None)
			C.WM_init( argc, argv )
			C.WM_keymap_init()

		#CTX_py_init_set(C, 1);
		#C.WM_keymap_init()
		#/* OK we are ready for it */
		#BLI_argsParse(ba, 4, load_file, C);
		ba.Free()
		if len(sys.argv) > 1 and not sys.argv[1].startswith('--'):
			self.load_blend_file( os.path.abspath(sys.argv[1]) )

		if '--headless' in sys.argv and False:
			blender.WM_exit(C)	# ton says this is incorrect



	def load_blend_file( self, url ):
		assert os.path.isfile( url )
		C = self.BContext
		print('trying to load...', url)
		blender.BLI_path_cwd( url )
		if '--headless' in sys.argv:
			ok = C.BKE_read_file(url, None)	# returns 0 on fail
			if ok:
				if False:
					wm = C.CTX_wm_manager()
					C.CTX_wm_manager_set(None)	# remove wm to force check
					blender.WM_check( C )
					#G.relbase_valid = 1;
					C.CTX_wm_manager_set( wm )	# reset wm
					blender.DAG_on_visible_update(C.data_main(), True)
				print('loaded blend file', url)
			else:
				print('ERROR: failed to load blend file', url)
		else:
			#/* we are not running in background mode here, but start blender in UI mode with
			# * a file - this should do everything a 'load file' does */
			#ReportList reports;
			#BKE_reports_init(&reports, RPT_PRINT);
			#WM_read_file(C, filename, &reports);
			#BKE_reports_clear(&reports);
			C.WM_read_file(url, None)

		#G.file_loaded = 1;

	def render_animation(self):
		scene = self.BContext.CTX_data_scene()
		re = blender.RE_NewRender( scene.C_id.name )
		re.BlenderAnim(
			self.BContext.CTX_data_main(),
			scene,
			None,
			scene.lay,
			1, #scene.r.sfra,
			10, #scene.r.efra,
			1, #scene.r.frame_step
		)

	def get_scene(self):
		return self.BContext.CTX_data_scene()

bpy = _bpy()
#bpy.data.next	# what are these?
#bpy.data.prev
#bpy.data.name

bpy.data.curlib	# pointer to Library
## these are all ListBase
## ListBase contains:
## first and last - POINTER(ctypes.c_void_p)
## checking DNA_listBase.h "first" and "last" really are void pointers
bpy.data.scene
bpy.data.library
bpy.data.C_object	# TODO change me to "object"
bpy.data.mesh
bpy.data.curve
bpy.data.mball
bpy.data.mat
bpy.data.tex
bpy.data.image
bpy.data.latt
bpy.data.lamp
bpy.data.camera
#bpy.data.ipo	# deprecated?
bpy.data.key
bpy.data.world
bpy.data.screen
#bpy.data.script	# deprecated?
bpy.data.vfont
bpy.data.text
bpy.data.speaker
bpy.data.sound
bpy.data.group
bpy.data.armature
bpy.data.action
bpy.data.nodetree
bpy.data.brush
bpy.data.particle
bpy.data.wm
bpy.data.gpencil
bpy.data.movieclip

#bpy.render_animation()

